import time
import requests
from datetime import datetime, timedelta
from django.shortcuts import render, redirect
from django.views.generic.base import View
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.hashers import make_password
from django.http import HttpResponseRedirect
from django.http import JsonResponse
from django.urls import reverse
from django.conf import settings
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from captcha.views import CaptchaStore
from utils.mixin_utils import LoginRequiredMixin
from utils.form_utils import get_form_errors
from systems.models import UserProfile, WeChatUser, Role
from systems.forms import LoginForm, ModifyPwdForm, RegistForm


class LoginView(View):
    def get(self, request):
        return render(request, 'systems/login.html')

    def post(self, request):
        v_next = request.request_data.get('next', '')
        v_form = LoginForm(request.POST)
        if v_form.is_valid():
            captcha = request.POST.get('captcha_1').strip()
            image_code = CaptchaStore.objects.filter(hashkey=request.POST.get('captcha_0').strip()).first()
            five_minute_ago = datetime.now() - timedelta(hours=0, minutes=settings.CAPTCHA_TIMEOUT, seconds=0)
            if image_code and five_minute_ago > image_code.expiration:
                image_code and image_code.delete()
                return render(request, 'systems/login.html', {'msg': "验证码过期"})
            else:
                if image_code and (image_code.response == captcha or image_code.challenge == captcha):
                    image_code and image_code.delete()
                else:
                    image_code and image_code.delete()
                    return render(request, 'systems/login.html', {'msg': "验证码错误"})

            user_name = request.POST.get('username').strip()
            pass_word = request.POST.get('password').strip()
            user = authenticate(username=user_name, password=pass_word)
            if user is not None:
                login(request, user)
                if v_next == '':
                    return HttpResponseRedirect(reverse('index'))
                else:
                    return HttpResponseRedirect(v_next)
        return render(request, 'systems/login.html', {'msg': get_form_errors(v_form)})


class LogoutView(View):
    def get(self, request):
        logout(request)
        response = redirect(reverse('systems:login'))
        response.delete_cookie('username')
        return response


class ResetPwdView(LoginRequiredMixin, View):
    """管理员重置用户密码"""

    def get(self, request, i_id):
        v_user = UserProfile.objects.get(id=i_id)
        v_user.password = make_password(settings.DEFAULT_PWD)
        v_user.save()
        return JsonResponse({'code': '200', 'msg': '重置成功'})


class ModifyPwdView(LoginRequiredMixin, View):
    """用户修改自己的密码"""

    def get(self, request):
        v_id = request.GET.get('id')
        return render(request, 'systems/user_pwd_modify.html', {'h_id': v_id})

    def post(self, request):
        v_form = ModifyPwdForm(request.POST)
        if v_form.is_valid():
            v_id = request.POST.get('id')

            if v_id is None or v_id == '':
                old_pwd = request.POST.get('pwd').strip()
                auth = authenticate(username=request.user.username, password=old_pwd)
                if auth is None:
                    return JsonResponse({'code': '444', 'msg': '旧密码错误'})

            pwd1 = request.POST.get('pwd1').strip()
            if v_id is None or v_id == '':
                user = UserProfile.objects.get(username=request.user.username)
                v_tip = '密码修改成功，请重新登陆'
            else:
                user = UserProfile.objects.get(id=int(v_id))
                v_tip = '密码重置成功'
            user.password = make_password(pwd1)
            user.save()
            return JsonResponse({'code': '200', 'msg': v_tip})
        else:
            return JsonResponse({'code': '444', 'msg': get_form_errors(v_form)})


class ClientLoginView(APIView):
    """客户端登录"""
    permission_classes = []
    authentication_classes = []

    def post(self, request):
        # ----------------------------------
        # 普通View的数据获取方法
        # ----------------------------------
        # Content-type为application/json时用下面的方法获取数据：
        # 方法一：
        # data_json = json.loads(request.body)
        # user_name = data_json.get('username')
        # pass_word = data_json.get('password')
        # 方法二：
        # if request.body.decode() == '':
        #     result = {'code': '999999', 'msg': '入参为空',
        #               'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
        #     return HttpResponse(json.dumps(result, ensure_ascii=False), content_type="application/json,charset=utf-8")
        # else:
        #     # 不为空就将body转换成字典
        #     body = eval(request.body)
        # user_name = body['username']
        # pass_word = body['password']
        #
        # ----------------------------------
        # APIView的数据获取方法
        # ----------------------------------
        # 如下：
        rdata = request.data
        user_name = rdata.get('username')
        pass_word = rdata.get('password')
        print(rdata.get('clientVer'))

        if user_name == '' or pass_word == '':
            result = {'code': '444444', 'msg': '用户名或密码为空',
                      'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
            return Response(result)
        user = authenticate(username=user_name, password=pass_word)
        if user is not None:
            login(request, user)
            # 生成Token方法一：使用自带的 TokenAuthentication
            # token, created = Token.objects.get_or_create(user=user)
            # token = token.key
            #
            # 生成Token方法二：使用 rest_framework_jwt.authentication.JSONWebTokenAuthentication
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            data = {'id': user.id, 'username': user_name, 'token': token}
            result = {'code': '000000', 'msg': '登录成功', 'data': data,
                      'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
            return Response(result)
        else:
            result = {'code': '444449', 'msg': '用户名或密码错误',
                      'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}
            return Response(result)


class ClientRegistView(APIView):
    """客户端：注册用户"""
    permission_classes = [AllowAny]
    authentication_classes = [JSONWebTokenAuthentication]

    def post(self, request):
        v_form = RegistForm(request.data)
        if v_form.is_valid():
            user_name = v_form.cleaned_data.get('username')
            pass_word = v_form.cleaned_data.get('password')
            dept_id = v_form.cleaned_data.get('dept_id')

            new_obj = UserProfile(username=user_name, name=user_name, dept_id=dept_id, dept_belong_id=dept_id)
            new_obj.password = make_password(pass_word)
            new_obj.creator = user_name
            new_obj.modifier = user_name
            new_obj.save()
            new_obj.role.add(3)
            return Response({'code': '000000', 'msg': '注册成功', 'data': new_obj.id,
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
        else:
            return Response({'code': '444444', 'msg': get_form_errors(v_form),
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})


def get_openid(wx_code):
    v_url = f'https://api.weixin.qq.com/sns/jscode2session?appid={settings.WX_APPID}&secret={settings.WX_SECRET}&js_code={wx_code}&grant_type=authorization_code'
    res = requests.get(v_url)
    return res.json().get('openid'), res.json().get('session_key'), res.json().get('unionid')


class WeChatLoginView(APIView):
    """微信登录"""
    permission_classes = []
    authentication_classes = []

    def post(self, request):
        wx_code = request.data.get('code')
        username = request.data.get('username')
        password = request.data.get('password')
        print(wx_code, username, password)
        if wx_code is None or wx_code == '':
            return Response({'code': '444444', 'msg': '微信 code 为空',
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})

        wx_openid, wx_session_key, wx_unionid = get_openid(wx_code)
        wechatuser = WeChatUser.objects.filter(openid=wx_openid)
        if bool(wechatuser):
            user = UserProfile.objects.get(id=wechatuser.server_user_id)
            login(request, user)
            # 生成Token：使用 rest_framework_jwt.authentication.JSONWebTokenAuthentication
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            data = {'id': user.id, 'username': user.username, 'name': user.name, 'token': token}
            return Response({'code': '000000', 'msg': '登录成功', 'data': data,
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
        else:
            return Response({'code': '444449', 'msg': '用户未绑定',
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})


class AppletLoginView(APIView):
    """小程序登录"""
    permission_classes = []
    authentication_classes = []

    def post(self, request):
        rdata = request.data
        username = rdata.get('username')
        password = rdata.get('password')
        login_role = request.data.get('role')
        print('小程序登录：', login_role, username, password)
        if username == '' or password == '':
            return Response({'code': '444444', 'msg': '用户名密码为空',
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})

        user = authenticate(username=username, password=password)
        if user is not None:
            if login_role == 'tuhao' and not bool(user.role.filter(key='tuhao')):
                return Response({'code': '444441', 'msg': '没有该土豪',
                                 'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
            if login_role == 'peiwan' and not bool(user.role.filter(key='complete')):
                return Response({'code': '444441', 'msg': '没有该陪玩',
                                 'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
            login(request, user)
            # 生成Token方法二：使用 rest_framework_jwt.authentication.JSONWebTokenAuthentication
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            data = {'id': user.id, 'username': username, 'token': token}
            return Response({'code': '000000', 'msg': '登录成功', 'data': data,
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
        else:
            return Response({'code': '444449', 'msg': '用户名密码错误',
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})


class AppletRegistView(APIView):
    """小程序注册用户"""
    permission_classes = [AllowAny]
    authentication_classes = [JSONWebTokenAuthentication]

    def post(self, request):
        v_form = RegistForm(request.data)
        if v_form.is_valid():
            user_role = request.data.get('role')
            user_name = v_form.cleaned_data.get('username')
            pass_word = v_form.cleaned_data.get('password')
            dept_id = v_form.cleaned_data.get('dept_id')
            print(user_role, user_name, pass_word, dept_id)

            new_obj = UserProfile(username=user_name, name=user_name, dept_id=dept_id, dept_belong_id=dept_id)
            new_obj.password = make_password(pass_word)
            new_obj.creator = user_name
            new_obj.modifier = user_name
            new_obj.save()
            if user_role == 'tuhao':
                new_obj.role.add(Role.objects.get(key='tuhao').id)  # 设置为角色：土豪
            if user_role == 'peiwan':
                new_obj.role.add(Role.objects.get(key='complete').id)  # 设置为角色：陪玩 任务完成人
            return Response({'code': '000000', 'msg': '注册成功', 'data': new_obj.id,
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
        else:
            return Response({'code': '444444', 'msg': get_form_errors(v_form),
                             'retTime': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())})
